package com.yugao.fintech.antelope.shop.service.impl;

import cn.hutool.core.date.DateTime;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.yitter.idgen.YitIdHelper;
import com.yugao.fintech.antelope.auth.AuthApi;
import com.yugao.fintech.antelope.auth.model.entity.LocalUser;
import com.yugao.fintech.antelope.auth.model.rqrs.LocalUserListReq;
import com.yugao.fintech.antelope.base.model.ThirdLoginResp;
import com.yugao.fintech.antelope.base.model.constants.SexEnum;
import com.yugao.fintech.antelope.base.model.constants.UserCons;
import com.yugao.fintech.antelope.base.model.module.auth.enums.LoginWayEnum;
import com.yugao.fintech.antelope.shop.assembly.UmsMemberAssembly;
import com.yugao.fintech.antelope.shop.manager.UmsMemberManager;
import com.yugao.fintech.antelope.shop.mapper.UmsMemberMapper;
import com.yugao.fintech.antelope.shop.model.entity.UmsMember;
import com.yugao.fintech.antelope.shop.model.rqrs.UmsMemberPageReq;
import com.yugao.fintech.antelope.shop.model.rqrs.UmsMemberReq;
import com.yugao.fintech.antelope.shop.model.rqrs.UmsMemberResp;
import com.yugao.fintech.antelope.shop.model.rqrs.UserStatusUpdateReq;
import com.yugao.fintech.antelope.shop.service.UmsMemberService;
import com.yugao.fintech.antelope.system.model.rqrs.log.LoginUserGetReq;
import com.yugao.fintech.framework.assistant.utils.StringUtils;
import com.yugao.fintech.framework.assistant.utils.exception.BizException;
import com.yugao.fintech.framework.core.page.PageModel;
import com.yugao.fintech.framework.core.page.TableSupport;
import com.yugao.fintech.framework.core.utils.IpUtils;
import com.yugao.fintech.framework.desensitization.annotations.FieldSensitiveHandle;
import com.yugao.fintech.framework.mybatisplus.utils.PageUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 用户
 *

 */
@Slf4j
@Service
public class UmsMemberServiceImpl extends ServiceImpl<UmsMemberMapper, UmsMember> implements UmsMemberService {

    @Autowired
    private UmsMemberManager umsMemberManager;

    @Autowired
    private UmsMemberAssembly fumUserAssembly;
    @Autowired
    private AuthApi authApi;

    /**
     * 分页查询 用户
     *
     * @return 返回分页数据
     */
    @Override
    @FieldSensitiveHandle
    public IPage<UmsMemberResp> pageUser(UmsMemberPageReq query) {
        PageModel pageModel = TableSupport.getPageModel();
        LocalDateTime beginTime = Optional.ofNullable(pageModel.getBeginDate()).map(DateTime::toLocalDateTime).orElse(null);
        LocalDateTime endTime = Optional.ofNullable(pageModel.getEndDate()).map(DateTime::toLocalDateTime).orElse(null);
        LambdaQueryWrapper<UmsMember> queryWrapper = UmsMember.lqw()
            .like(StringUtils.isNotEmpty(query.getUserName()), UmsMember::getUserName, query.getUserName())
            .like(StringUtils.isNotEmpty(query.getNickName()), UmsMember::getNickName, query.getNickName())
            .eq(StringUtils.isNotEmpty(query.getStatus()), UmsMember::getStatus, query.getStatus())
            .eq(StringUtils.isNotEmpty(query.getSourceType()), UmsMember::getSourceType, query.getSourceType())
            .ge(Objects.nonNull(beginTime), UmsMember::getCreatedAt, beginTime)
            .le(Objects.nonNull(endTime), UmsMember::getCreatedAt, endTime)
            .orderByDesc(UmsMember::getCreatedAt);
        IPage<UmsMember> records = this.page(PageUtil.to(pageModel), queryWrapper);

        List<Long> userIds = records.getRecords().stream().map(UmsMember::getUserId).collect(Collectors.toList());

        LocalUserListReq authQuery = LocalUserListReq.builder().userIds(userIds)
                .sources(Collections.singletonList(UserCons.Source.SYS_ADMIN.getCode())).build();
        Map<Long, LocalUser> localUserMap = authApi.listAuth(authQuery).stream()
                .collect(Collectors.toMap(LocalUser::getUserId, Function.identity()));

        return PageUtil.to(records, (e) -> {
            UmsMemberResp rs = fumUserAssembly.toUserRS(e);
            rs.setAccount(localUserMap.get(rs.getUserId()));
            return rs;
        });
    }

    /**
     * 根据主键查询 用户
     *
     * @return 返回记录，没有返回null
     */
    @Override
    @FieldSensitiveHandle
    public UmsMemberResp getUserById(Long userId) {
        UmsMember umsMember = this.getById(userId);
        if (Objects.isNull(umsMember)) {
            return null;
        }
        UmsMemberResp rs = fumUserAssembly.toUserRS(this.getById(userId));
        rs.setAccount(authApi.getUserByUserId(umsMember.getUserId()));
        return rs;
    }

    /**
     * 更新 用户
     *
     * @param rq 修改的记录
     * @return 返回影响行数
     */
    @Override
    public boolean updateUserById(UmsMemberReq rq) {
        UmsMember entity = fumUserAssembly.toUser(rq);
    	return this.updateById(entity);
    }

    /**
     * 通过id删除 用户
     *
     * @return 返回影响行数
     */
    @Override
    public boolean deleteUserById(Long userId) {
    	return this.removeById(userId);
    }

    @Override
    public UmsMember autoRegister(LoginUserGetReq rq) {
        if (LoginWayEnum.LOCAL.getCode().equals(rq.getLoginWay())) {
            throw new BizException("非第三方登录不支持自动注册");
        }
        ThirdLoginResp thirdLogin = Optional.ofNullable(rq.getThirdLogin()).orElse(new ThirdLoginResp());
        UmsMember umsMember = UmsMember.builder().userId(rq.getUserId())
                .userName(YitIdHelper.nextId() + "").sex(SexEnum.UNKNOWN.getCode())
                .nickName(thirdLogin.getNickName()).city(thirdLogin.getCity())
                .avatar(thirdLogin.getAvatarUrl()).createdAt(new Date())
                .loginIp(IpUtils.getHostIp()).build();
        if (!this.save(umsMember)) {
            throw new BizException("自动注册失败, 请联系管理员");
        }
        return umsMember;
    }

    @Override
    public void batchUpdateStatus(UserStatusUpdateReq rq) {
        List<Long> userIds = StringUtils.toList(rq.getIds(), ",", Long.class, (userId) -> {
            if (UserCons.ADMIN_ID.equals(userId)) {
                throw new BizException("不允许操作管理员");
            }
        });

        LambdaQueryWrapper<UmsMember> lqw = UmsMember.lqw().in(UmsMember::getUserId, userIds);
        UmsMember user =  new UmsMember();
        user.setStatus(rq.getStatus());
        if (!this.update(user, lqw)) {
            throw new BizException("用户状态更新失败, 请联系管理员");
        }
        // 更新状态之后, 删除用户登录状态
        userIds.forEach(authApi::removeAccessTokenByUserId);

        List<LocalUser> localUserList = userIds.stream()
                .map(e -> LocalUser.builder().userId(e).status(rq.getStatus()).build())
                .collect(Collectors.toList());
        authApi.batchUpdateLocalUser(localUserList);
    }
}
